package io.github.jyrmc.gmcp.task

import io.github.jyrmc.gmcp.enums.FileStrategyType
import io.github.jyrmc.gmcp.utils.GenerateCodeUtil
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

/**
 * 创建于 2020-01-08 16:37
 *
 * @author jiangyun
 * @类说明 任务类
 */
open class GenerateCodeTask : DefaultTask() {
    @Input
    @Optional
    lateinit var dbType: String                 // 数据库类型
    @Input
    @Optional
    lateinit var url: String                    // 数据库连接地址
    @Input
    var port: Int = 3306                        // 端口
    @Input
    @Optional
    lateinit var database: String               // 数据库名称
    @Input
    @Optional
    lateinit var userName: String               // 用户名
    @Input
    @Optional
    lateinit var password: String               // 密码
    @Input
    @Optional
    lateinit var frameworkType: String          // 框架类型(mybatis或mybatisplus)
    @Input
    @Optional
    lateinit var tablePrefix: String            // 表前缀
    @Input
    @Optional
    lateinit var tableNames: MutableList<String> // 表名称
    @Input
    @Optional
    lateinit var ignoreColumns: MutableList<String> // 需要忽略的列
    @Input
    @Optional
    lateinit var projectPath: String            // 项目绝对路径
    @Input
    @Optional
    lateinit var packageName: String            // 包名称
    @Input
    @Optional
    lateinit var controller: String             // 控制器文件夹名称
    @Input
    @Optional
    lateinit var service: String                // 业务层文件夹名称
    @Input
    @Optional
    lateinit var mapper: String                 // dao层文件夹名称
    @Input
    @Optional
    lateinit var entity: String                 // 实体文件夹名称
    @Input
    @Optional
    lateinit var xml: String                    // dao层对应xml文件夹名称
    @Input
    @Optional
    lateinit var languageType: String           // 语言类型，目前只支持java和kotlin
    @Input
    @Optional
    lateinit var author: String                 // 作者
    @Input
    @Optional
    lateinit var apiPrefix: String              // 接口前缀
    @Input
    var restfulStyle: Boolean = true            // 是否生成restful接口
    @Input
    var swagger: Boolean = true                 // 是否允许生成doc
    //lateinit var isServerH2: Int              // 是否为独立服务h2数据库
    @Input
    @Optional
    lateinit var fileGenStrategy: String // 文件生成策略：createIfNotExists-如果已存在则不覆盖生成(默认值)，cover-如果已存在则覆盖生成，createNew-如果已存在文件则新建

    @TaskAction
    fun generateAction() {
        if (dbType.isBlank()) {
            println("database type can't be null or empty")
            return
        }
        /*if (dbType != "mysql" || dbType != "postgresql") {
            printlnln("database type only surport mysql or postgresql")
            return
        }*/
        if (url.isBlank()) {
            println("url can't be null or empty")
            return
        }
        if (database.isBlank()) {
            println("databaseName can't be null or empty")
            return
        }
        if (userName.isBlank()) {
            println("userName can't be null or empty")
            return
        }
        if (password.isBlank()) {
            println("password can't be null or empty")
            return
        }
        if (frameworkType.isBlank()) {
            println("password can't be null or empty")
            return
        }
        if (tablePrefix.isBlank()) {
            println("frameworkType can't be null or empty")
            return
        }
        if (tableNames.isEmpty()) {
            println("tableNames can't be null or empty")
            return
        }
        if (projectPath.isBlank()) {
            println("projectPath can't be null or empty")
            return
        }
        if (packageName.isBlank()) {
            println("packageName can't be null or empty")
            return
        }
        if (controller.isBlank()) {
            println("controller can't be null or empty")
            return
        }
        if (service.isBlank()) {
            println("service can't be null or empty")
            return
        }
        if (mapper.isBlank()) {
            println("mapper can't be null or empty")
            return
        }
        if (entity.isBlank()) {
            println("entity can't be null or empty")
            return
        }
        if (xml.isBlank()) {
            println("xml can't be null or empty")
            return
        }
        if (languageType.isBlank()) {
            println("languageType can't be null or empty")
            return
        }
        if (author.isBlank()) {
            println("author can't be null or empty")
            return
        }
        if (languageType != "java" && languageType != "kotlin") {
            println("only surpport generate java or kotlin code")
            return
        }
        if (apiPrefix.isBlank()) {
            // apiPrefix = "api"
            apiPrefix = ""
            println("default api prefix is:/api")
        }

        val strtegy: FileStrategyType = getFileStrategyType(fileGenStrategy)

        url = when(dbType) {
            "mysql" -> "jdbc:mysql://${url}:${port}/${database}?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&autoReconnect=true&failOverReadOnly=false&tinyInt1isBit=false"
            "postgresql" -> "jdbc:postgresql://${url}:${port}/${database}"
            // "h2" -> "jdbc:h2:"
            else -> ""
        }

        try {
            println("========================== start generate code ==========================")
            println("========================== author: iwiteks-jy  ==========================")
            GenerateCodeUtil.generateCode(
                dbType,
                url,
                database,
                userName,
                password,
                frameworkType,
                tablePrefix,
                tableNames,
                ignoreColumns,
                projectPath,
                packageName,
                controller,
                service,
                mapper,
                entity,
                xml,
                languageType,
                author,
                apiPrefix,
                restfulStyle,
                swagger,
                strtegy,
            )
        } catch (ex: Exception) {
            println(ex)
        } finally {
            println("========================== end generate code ==========================")
        }
    }

    /**
     * 获取策略
     *
     * @param value 策略名称
     */
    fun getFileStrategyType(value: String): FileStrategyType {
        return when (value) {
            "createIfNotExists" -> FileStrategyType.CREATE_IF_NOT_EXISTS
            "cover" -> FileStrategyType.COVER
            "createNew" -> FileStrategyType.CREATE_NEW
            else -> FileStrategyType.CREATE_IF_NOT_EXISTS
        }
    }
}